#include <ResultManager.h>

void Retrieve::perform()
{

  /* LA BANDA DE INTERPOLACION ES DIEZ, CAMBIAR CUANDO SEA NECESARIO */
  TZone finalZone;
  int posx = 0, posy = 0;
  int ib = 10;
  
  cout << endl << "Zone: " << _zone.id << endl;
  IceUtil::Time start = IceUtil::Time::now();
  //Recovering File
  _file.getFile();
  IceUtil::Time end = IceUtil::Time::now() - start;
  cout << "\tRecovering Time: " << end.toSecondsDouble() << endl;

  //Composing the image, if it is a static frame
  if(this->_sceneType == 0){
    try{
      start = IceUtil::Time::now();
      finalZone = getFinalDimensions(_zone, ib, _width, _height);
      
      //Obtaining Mask for transparency
      Image filterWhite(Geometry(finalZone.x2 - finalZone.x1, finalZone.y2 - finalZone.y1), "black");
      Image filterBlack(Geometry(_zone.x2 - _zone.x1, _zone.y2 - _zone.y1), "white");
      
      if(finalZone.x1 != _zone.x1)
	posx += ib;
      if(finalZone.y1 != _zone.y1)
	posy += ib;
      
      //Composing mask and Applying gaussian filter
      filterWhite.composite(filterBlack, posx, posy, OverCompositeOp);
      filterWhite.gaussianBlur(ib/2, 20);
      Image source(_file.getFileName());
      
      //Obtaining transparency values
      for(int i = 0; i < finalZone.x2 - finalZone.x1; i++)
	for(int j = 0; j < finalZone.y2 - finalZone.y1; j++){
	  Color pix = filterWhite.pixelColor(i, j);
	  filterWhite.pixelColor(i, j, Color(pix.redQuantum(), pix.greenQuantum(), pix.blueQuantum(), pix.redQuantum()));
	}
      
      //Chopping and cropping the image
      source.chop(Geometry(finalZone.x1, finalZone.y1));
      source.crop(Geometry(finalZone.x2 - finalZone.x1, finalZone.y2 - finalZone.y1));

      //Copying opacicity
      source.composite(filterWhite, 0, 0, CopyOpacityCompositeOp);
      Image result(_image);
      result.modifyImage();

      //Composing and writing the final result
      result.composite(source, finalZone.x1, finalZone.y1, PlusCompositeOp);
      result.write(_image);
      end = IceUtil::Time::now() - start;
      cout << "\tComposing time: " << end.toSecondsDouble() << endl;
    }
    catch(Exception& err)
      {
	cout << "Exception composing Image: " << err.what() << endl;
      }
  }
  _cb->ice_response();
}
  
  void Retrieve::cancel()
  {
  _cb->ice_exception(Ice::ObjectNotExistException(__FILE__, __LINE__));
}

TZone Retrieve::getFinalDimensions(TZone z, int ib, int width, int height){
  TZone result;
  
  result = z;
  
  if(result.x1 - ib >= 0)
    result.x1 -= ib;
  
  if(result.y1 - ib >= 0)
    result.y1 -= ib;
  
  if(result.x2 + ib <= width)
    result.x2 += ib;

  if(result.y2 + ib <= height)
    result.y2 += ib;

  return result;
}

void ResultManager::add(const AMD_YafridngRenderManager_updateZonePtr& cb,
			const int width,
			const int height,
			const TZone& zone,
			const string& result,
			const FileManager& file)
{
  Lock sync(*this);
  RetrievePtr ret = new Retrieve(cb, width, height, zone, this->_image, this->_sceneType, result, file);
  _retrieves.push_back(ret);
}

bool ResultManager::perform()
{
  Lock sync(*this);
  if(!_retrieves.empty()){
    _retrieves.at(0)->perform();
    _retrieves.erase(_retrieves.begin());
  }

  if(_lastZone && _retrieves.empty())
    _destroy = true;
  return _destroy;
}

void ResultManager::lastZone()
{
  Lock sync(*this);
  _lastZone = true;
}

void ResultManager::destroy()
{
  Lock sync(*this);
  assert(!_destroy);
  if(!_retrieves.empty()){
    vector<RetrievePtr>::const_iterator p;
    for(p = _retrieves.begin(); p != _retrieves.end(); ++p)
      {
	(*p)->cancel();
      }
  }
  _destroy = true;
  notifyAll();
}

bool ResultManager::getDestroy()
{
  Lock sync(*this);
  return _destroy;
}
